﻿using SharpCompress.Archives;
using SharpCompress.Common;
using SharpCompress.Readers;
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XYS.Core.Models;
using XYS.Core.Util;

namespace XYS.Service.Core.Util.Helper
{
    /// <summary>
    /// 压缩包 帮助类
    /// </summary>
    public static class ZIPHelper
    {
        /// <summary>
        /// 解压缩文件
        /// </summary>
        /// <param name="zipFileName">压缩包文件</param>
        /// <param name="unzipPath">解压目录</param>
        /// <returns></returns>
        public static ResultModel Unzip(string zipFileName, string unzipPath)
        {
            unzipPath = unzipPath.Replace("\\", "/");

            if (!File.Exists(zipFileName)) return ResultModel.Failed($"文件不存在[{zipFileName}]");

            // 确保目标文件夹存在
            if (!string.IsNullOrWhiteSpace(unzipPath))
            {
                if (!Directory.Exists(unzipPath))
                    Directory.CreateDirectory(unzipPath);
            }

            //设置默认解压字符
            ReaderOptions options = new();
            options.ArchiveEncoding.Default = Encoding.GetEncoding("utf-8");
            using var archive = ArchiveFactory.Open(zipFileName, options);
            foreach (IArchiveEntry entry in archive.Entries)
            {
                if (!entry.IsDirectory)
                {
                    var fullPath = Path.Combine(new DirectoryInfo(unzipPath).FullName, entry.Key.ToString().Replace("\\", "/"));
                    var fullDir = Path.GetDirectoryName(fullPath);
                    if (!Directory.Exists(fullDir)) Directory.CreateDirectory(fullDir);

                    entry.WriteToFile(fullPath, new ExtractionOptions { ExtractFullPath = true, Overwrite = true });
                }
            }

            return ResultModel.Success;
        }


        /// <summary>
        /// 文件夹压缩
        /// </summary>
        /// <param name="sourceDirectory"></param>
        /// <param name="zipFilePath"></param>
        /// <returns></returns>
        public static ResultModel ZipDirectory(string sourceDirectory, string zipFilePath)
        {
            zipFilePath = zipFilePath.Replace("\\", "/");
            try
            {
                if (File.Exists(zipFilePath))
                    File.Delete(zipFilePath);

                ZipFile.CreateFromDirectory(sourceDirectory, zipFilePath, CompressionLevel.Optimal, true);
            }
            catch (Exception ex)
            {
                return ResultModel.Failed(ex.ToJson());
            }
            return ResultModel.Success;
        }

        /// <summary>
        /// 文件压缩
        /// </summary>
        /// <param name="filesToCompres"></param>
        /// <param name="zipFilePath"></param>
        /// <returns></returns>
        public static ResultModel ZipFiles(string filesToCompres, string zipFilePath)
        {
            zipFilePath = zipFilePath.Replace("\\", "/");
            return ZipFiles(new List<string>() { filesToCompres }, zipFilePath);
        }


        /// <summary>
        /// 文件压缩
        /// </summary>
        /// <param name="filesToCompress"></param>
        /// <param name="zipFilePath"></param>
        /// <returns></returns>
        public static ResultModel ZipFiles(List<string> filesToCompress, string zipFilePath)
        {
            zipFilePath = zipFilePath.Replace("\\", "/");
            try
            {
                using FileStream zipToCreate = new(zipFilePath, FileMode.Create);
                using ZipArchive archive = new(zipToCreate, ZipArchiveMode.Create);
                foreach (string fileToCompress in filesToCompress)
                {
                    string fileNameInArchive = Path.GetFileName(fileToCompress);
                    archive.CreateEntryFromFile(fileToCompress, fileNameInArchive, CompressionLevel.Optimal);
                }
            }
            catch (Exception ex)
            {
                return ResultModel.Failed(ex.ToJson());
            }
            return ResultModel.Success;
        }


    }

}
